/*
 *
 *  * Copyright 2023  腾羚智能, Inc. All rights reserved.
 *
 */

package cn.wuxing.mediation.businessplatform.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.json.JSONUtil;
import cn.wuxing.mediation.businessplatform.domain.annotation.DictLabel;
import cn.wuxing.mediation.businessplatform.domain.dto.ApplicantDTO;
import cn.wuxing.mediation.businessplatform.domain.dto.BaseBusinessOperateDTO;
import cn.wuxing.mediation.businessplatform.domain.dto.DelDTO;
import cn.wuxing.mediation.businessplatform.domain.dto.MediationRecordDTO;
import cn.wuxing.mediation.businessplatform.domain.enums.EventStateEnum;
import cn.wuxing.mediation.businessplatform.domain.enums.OperatingTypeEnum;
import cn.wuxing.mediation.businessplatform.domain.pojo.AreaVO;
import cn.wuxing.mediation.businessplatform.domain.pojo.EventOperateVO;
import cn.wuxing.mediation.businessplatform.domain.vo.ApplicantDetailVO;
import cn.wuxing.mediation.businessplatform.domain.vo.BaseBusinessDetailVO;
import cn.wuxing.mediation.businessplatform.domain.vo.MediationRecordDetailVO;
import cn.wuxing.mediation.businessplatform.listener.event.OrganizationEvent;
import cn.wuxing.mediation.businessplatform.mapper.business.CmEventApplicantMapper;
import cn.wuxing.mediation.businessplatform.mapper.business.CmEventFileMapper;
import cn.wuxing.mediation.businessplatform.mapper.business.CmMediationRecordMapper;
import cn.wuxing.mediation.businessplatform.mapper.business.CmOperatingRecordMapper;
import cn.wuxing.mediation.businessplatform.mapper.infoconfig.MediatorCommitteeMapper;
import cn.wuxing.mediation.businessplatform.mapper.infoconfig.WindowMapper;
import cn.wuxing.mediation.businessplatform.mapper.system.AreaMapper;
import cn.wuxing.mediation.businessplatform.mapper.system.DeptMapper;
import cn.wuxing.mediation.businessplatform.service.BaseBusinessOperateService;
import cn.wuxing.mediation.common.core.domain.entity.CmEventApplicant;
import cn.wuxing.mediation.common.core.domain.entity.CmEventFile;
import cn.wuxing.mediation.common.core.domain.entity.CmMediationRecord;
import cn.wuxing.mediation.common.core.domain.entity.CmOperatingRecord;
import cn.wuxing.mediation.common.core.domain.entity.IcWindow;
import cn.wuxing.mediation.common.core.domain.entity.SysDept;
import cn.wuxing.mediation.common.core.domain.entity.SysDictData;
import cn.wuxing.mediation.common.core.domain.model.LoginUser;
import cn.wuxing.mediation.common.exception.ServiceException;
import cn.wuxing.mediation.common.utils.DesensitizedUtil;
import cn.wuxing.mediation.common.utils.SecurityUtils;
import cn.wuxing.mediation.common.utils.StringUtils;
import cn.wuxing.mediation.common.utils.bean.BeanUtils;
import cn.wuxing.mediation.common.utils.des.DESUtil;
import cn.wuxing.mediation.system.domain.MessageNotifications;
import cn.wuxing.mediation.system.mapper.SysUserMapper;
import cn.wuxing.mediation.system.service.ISMSGNotificationsService;
import cn.wuxing.mediation.system.service.ISysDictDataService;
import cn.wuxing.mediation.system.util.Desensitization;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * @description: 业务列表查询
 * @author:
 * @date 2023-09-07 9:59
 * @version: 1.0 <br>
 */
@Slf4j
@Service
@SuppressWarnings("all")
public abstract class BaseBusinessOperateServiceImpl<F extends BaseBusinessOperateDTO, V extends BaseBusinessDetailVO> implements
        BaseBusinessOperateService {

    @Autowired
    private DeptMapper deptMapper;

    @Autowired
    private WindowMapper windowMapper;

    @Autowired
    private MediatorCommitteeMapper mediatorCommitteeMapper;

    @Autowired
    private CmEventApplicantMapper cmEventApplicantMapper;

    @Autowired
    private CmOperatingRecordMapper cmOperatingRecordMapper;

    @Autowired
    private CmMediationRecordMapper cmMediationRecordMapper;

    @Autowired
    private CmEventFileMapper cmEventFileMapper;

    @Autowired
    private AreaMapper areaMapper;

    @Autowired
    private ISMSGNotificationsService ismsgNotificationsService;

    @Autowired
    private ISysDictDataService sysDictDataService;

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private ApplicationEventPublisher applicationEventPublisher;

    @Override
    public boolean del(DelDTO dto) {
        if (CollUtil.isEmpty(dto.getIds())) {
            return Boolean.FALSE;
        }

        // 删除事件
        return this.delEvent(dto);

    }

    @Override
    public BaseBusinessDetailVO getEventDetail(Long id) {
        // 获取事件信息
        V vo = this.getEventInfoDetail(id);
        if (null == vo) {
            return new BaseBusinessDetailVO();
        }
        this.handlerDictLabel(vo);
        // 所属区域
        this.getArea(vo);
        // 获取当事人信息
        this.getApplicantInfoDetail(vo);

        // 获取调解记录
        this.getMediationRecordDetail(vo);

        // 获取事项文件
        this.getEventFileDetail(vo);

        // 获取操作记录
        List<CmOperatingRecord> cmOperatingRecords = this.cmOperatingRecordMapper.selectList(
                Wrappers.<CmOperatingRecord>lambdaQuery().eq(CmOperatingRecord::getEventId, id)
                        .eq(CmOperatingRecord::getEventCategory, vo.getEventCategory()));
        if (CollUtil.isNotEmpty(cmOperatingRecords)) {
            cmOperatingRecords.forEach(item -> {
                if (StringUtils.isNotBlank(item.getOperatingType())) {
                    item.setOperatingType(OperatingTypeEnum.getDesc(Integer.parseInt(item.getOperatingType())));
                }
            });
        }
        vo.setCmOperatingRecords(cmOperatingRecords);

        return vo;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void operateEvent(String paramsJson) {
        //获取入参
        F f = this.getCreatedDescription(paramsJson);
        log.info("BaseTransferOwnershipService [] saveTransferOwnership f :{}", JSONUtil.toJsonStr(f));

        // 入参校验
        this.checkParams(f);

        // 事件信息保存
        EventOperateVO event = this.saveEvent(f);
        if (null == event) {
            return;
        }
        // 处理记录
        this.handerRecord(f, event);

        // 当事人信息保存
        this.saveApplicant(f, event.getId());

        // 保存调解记录
        this.saveMediateRecord(f, event.getId(), event.getEventState());

        // 保存文件
        this.saveEventFile(f, event.getId());

    }

    F getCreatedDescription(String paramsJson) {

        //获取详情的泛型
        return (F) JSONObject.parseObject(paramsJson, BeanUtils.doInstanceClass(this.getClass(), 0));
    }


    protected void getEventFileDetail(BaseBusinessDetailVO vo) {

        // 1.人民调解申请书或人民调解受理登记表
        // 2.人民调解当事人权利义务告知书
        // 3.当事人身份证明
        // 4.授权委托书
        // 5.人民调解调查记录
        // 6.人民调解证据材料
        // 7.人民调解记录
        // 8.人民调解协议书
        // 9.人民调解协议书履行凭证
        // 10.人民调解回访记录
        // 11.司法确认有关材料
        // 12.卷宗情况说明
        // 13.封底
        // 16 证据材料
        // 17 附件
        // 18 结案附件
        List<CmEventFile> cmEventFiles = this.cmEventFileMapper.selectList(
                Wrappers.<CmEventFile>lambdaQuery().eq(CmEventFile::getEventId, vo.getId())
                        .eq(CmEventFile::getEventCategory, vo.getEventCategory())
                        .eq(CmEventFile::getDelFlag, 0));
        if (CollUtil.isEmpty(cmEventFiles)) {
            return;
        }
        for (CmEventFile cmEventFile : cmEventFiles) {
            cmEventFile.setFileUrl(cmEventFile.getFileUrl());
        }
        vo.setCmEventFilesVO(cmEventFiles.stream().filter(i -> "17".equals(i.getFileType()))
                .collect(Collectors.toList()));

        List<String> dossierTypes = Arrays.asList("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13");

        vo.setDossierFilesVO(cmEventFiles.stream().filter(i -> dossierTypes.contains(i.getFileType()))
                .collect(Collectors.toList()));

        List<String> proofTypes = Arrays.asList("16", "17");

        vo.setProofFilesVO(cmEventFiles.stream().filter(i -> dossierTypes.contains(i.getFileType()))
                .collect(Collectors.toList()));

        vo.setClosCaseFilesVO(cmEventFiles.stream().filter(i -> "18".equals(i.getFileType()))
                .collect(Collectors.toList()));
    }

    protected void getMediationRecordDetail(BaseBusinessDetailVO vo) {
        List<CmMediationRecord> cmMediationRecords = this.cmMediationRecordMapper.selectList(
                Wrappers.<CmMediationRecord>lambdaQuery().eq(CmMediationRecord::getEventId, vo.getId())
                        .eq(CmMediationRecord::getEventCategory, vo.getEventCategory())
                        .orderByDesc(CmMediationRecord::getCreateTime).last("limit 1"));
        if (CollUtil.isEmpty(cmMediationRecords)) {
            return;
        }
        List<MediationRecordDetailVO> mediationRecordDetailVOList = new ArrayList<>();
        cmMediationRecords.forEach(cmMediationRecord -> {
            MediationRecordDetailVO mediationRecordDetailVO = new MediationRecordDetailVO();
            BeanUtils.copyProperties(cmMediationRecord, mediationRecordDetailVO);
            this.handlerDictLabel(mediationRecordDetailVO);
            mediationRecordDetailVOList.add(mediationRecordDetailVO);
        });

        vo.setMediationRecordDetailVO(mediationRecordDetailVOList);
    }

    protected void getApplicantInfoDetail(BaseBusinessDetailVO vo) {
        List<CmEventApplicant> cmEventApplicants = this.cmEventApplicantMapper.selectList(
                Wrappers.<CmEventApplicant>lambdaQuery().eq(CmEventApplicant::getEventId, vo.getId())
                        .eq(CmEventApplicant::getEventCategory, vo.getEventCategory()));
        List<ApplicantDetailVO> applicantDetailVOList = new ArrayList<>();
        cmEventApplicants.forEach(item -> {
            ApplicantDetailVO applicantDetailVO = BeanUtil.copyProperties(item, ApplicantDetailVO.class);
            this.handlerDictLabel(applicantDetailVO);
            // 解密 脱敏
            this.decrypt(applicantDetailVO);
            applicantDetailVOList.add(applicantDetailVO);
        });
        vo.setApplicantDetailVOList(applicantDetailVOList);

    }

    /**
     * 加密
     *
     * @param item
     * @param cmEventApplicant
     */
    private void decrypt(ApplicantDetailVO cmEventApplicant) {
        // 姓名
        if (StringUtils.isNotBlank(cmEventApplicant.getName())) {
            cmEventApplicant.setName(
                    Desensitization.custNameDesensitization(DESUtil.decrypt(cmEventApplicant.getName())));
        }
        // 姓名
        if (StringUtils.isNotBlank(cmEventApplicant.getProxyUserName())) {
            cmEventApplicant.setProxyUserName(
                    Desensitization.custNameDesensitization(DESUtil.decrypt(cmEventApplicant.getProxyUserName())));
        }
        // 手机号
        if (StringUtils.isNotBlank(cmEventApplicant.getPhone())) {
            cmEventApplicant.setPhone(
                    Desensitization.mobilePhoneDesensitization((DESUtil.decrypt(cmEventApplicant.getPhone()))));
        }
        // 手机号
        if (StringUtils.isNotBlank(cmEventApplicant.getProxyUserPhone())) {
            cmEventApplicant.setProxyUserPhone(
                    Desensitization.mobilePhoneDesensitization(DESUtil.decrypt(cmEventApplicant.getProxyUserPhone())));
        }
        // 身份证
        if (StringUtils.isNotBlank(cmEventApplicant.getIdCard())) {
            cmEventApplicant.setIdCard(
                    Desensitization.idCardDesensitization(DESUtil.decrypt(cmEventApplicant.getIdCard())));
        }
        // 身份证
        if (StringUtils.isNotBlank(cmEventApplicant.getProxyUserIdCard())) {
            cmEventApplicant.setProxyUserIdCard(
                    Desensitization.idCardDesensitization(DESUtil.decrypt(cmEventApplicant.getProxyUserIdCard())));
        }
        // 统一社会信用代码
        if (StringUtils.isNotBlank(cmEventApplicant.getUscc())) {
            cmEventApplicant.setUscc(
                    Desensitization.idCardDesensitization(DESUtil.decrypt(cmEventApplicant.getUscc())));
        }
        // 组织名称
        if (StringUtils.isNotBlank(cmEventApplicant.getCompanyName())) {
            cmEventApplicant.setCompanyName(Desensitization.idCardDesensitization(cmEventApplicant.getCompanyName()));
        }
    }


    abstract Boolean delEvent(DelDTO dto);

    abstract V getEventInfoDetail(Long id);

    abstract EventOperateVO saveEvent(F f);

    protected void saveEventFile(F f, Long eventId) {
        List<CmEventFile> eventFileDTOS = f.getEventFileDTOS();

        this.cmEventFileMapper.delete(Wrappers.<CmEventFile>lambdaQuery().eq(CmEventFile::getEventId, eventId)
                .eq(CmEventFile::getEventCategory, f.getEventCategory())
                .in(CmEventFile::getFileType, Arrays.asList("17")));

        if (CollUtil.isEmpty(eventFileDTOS)) {
            return;
        }

        eventFileDTOS.forEach(item -> {
            item.setEventId(eventId);
            if (StringUtils.isBlank(item.getFileType())) {
                item.setFileType("17");
            }
            item.setCreateBy(SecurityUtils.getUsername());
            item.setCreateTime(DateTime.now());
            item.setEventCategory(f.getEventCategory());
            this.cmEventFileMapper.insert(item);
        });
    }

    protected void saveMediateRecord(F f, Long eventId, Integer eventState) {
        MediationRecordDTO mediationRecordDTO = f.getMediationRecordDTO();
        if (null == mediationRecordDTO) {
            return;
        }
        List<CmMediationRecord> mediationRecords = this.cmMediationRecordMapper.selectList(
                Wrappers.<CmMediationRecord>lambdaQuery()
                        .select(CmMediationRecord::getId)
                        .eq(CmMediationRecord::getEventId, eventId)
                        .orderByDesc(CmMediationRecord::getCreateTime));
        CmMediationRecord cmMediationRecord = new CmMediationRecord();
        BeanUtils.copyProperties(mediationRecordDTO, cmMediationRecord);
        cmMediationRecord.setEventId(eventId);
        cmMediationRecord.setEventCategory(f.getEventCategory());
        if (CollUtil.isEmpty(mediationRecords) ||
                (EventStateEnum.WAIT_SECOND_MEDIATE.getCode().equals(eventState)) && mediationRecords.size() < 2
        ) {
            cmMediationRecord.setCreateBy(SecurityUtils.getUsername());
            cmMediationRecord.setCreateTime(DateTime.now());
            this.cmMediationRecordMapper.insert(cmMediationRecord);
        } else {
            cmMediationRecord.setId(mediationRecords.get(0).getId());
            cmMediationRecord.setUpdateBy(SecurityUtils.getUsername());
            cmMediationRecord.setUpdateTime(DateTime.now());
            this.cmMediationRecordMapper.updateById(cmMediationRecord);
        }


    }

    protected void saveApplicant(F f, Long eventId) {
        log.info("saveApplicant applicantDTOS :{}", JSONUtil.toJsonStr(f.getApplicantDTOS()));
        if (CollUtil.isEmpty(f.getApplicantDTOS())) {
            return;
        }

        this.cmEventApplicantMapper.delete(
                Wrappers.<CmEventApplicant>lambdaQuery().eq(CmEventApplicant::getEventId, eventId)
                        .eq(CmEventApplicant::getEventCategory, f.getEventCategory()));

        f.getApplicantDTOS().forEach(item -> {
            CmEventApplicant cmEventApplicant = BeanUtil.copyProperties(item, CmEventApplicant.class);
            cmEventApplicant.setCreateBy(SecurityUtils.getUsername());
            cmEventApplicant.setCreateTime(DateTime.now());
            cmEventApplicant.setEventId(eventId);
            cmEventApplicant.setEventCategory(f.getEventCategory());
            // 加密
            this.encryptInfo(item, cmEventApplicant);

            this.cmEventApplicantMapper.insert(cmEventApplicant);
        });
    }

    /**
     * 加密
     *
     * @param item
     * @param cmEventApplicant
     */
    private void encryptInfo(ApplicantDTO item, CmEventApplicant cmEventApplicant) {
        // 姓名
        if (StringUtils.isNotBlank(item.getName())) {
            cmEventApplicant.setName(DESUtil.encrypt(item.getName()));
        }
        // 姓名
        if (StringUtils.isNotBlank(item.getProxyUserName())) {
            cmEventApplicant.setProxyUserName(DESUtil.encrypt(item.getProxyUserName()));
        }
        // 手机号
        if (StringUtils.isNotBlank(item.getPhone())) {
            cmEventApplicant.setPhone(DESUtil.encrypt(item.getPhone()));
        }
        // 手机号
        if (StringUtils.isNotBlank(item.getProxyUserPhone())) {
            cmEventApplicant.setProxyUserPhone(DESUtil.encrypt(item.getProxyUserPhone()));
        }
        // 身份证
        if (StringUtils.isNotBlank(item.getIdCard())) {
            cmEventApplicant.setIdCard(DESUtil.encrypt(item.getIdCard()));
        }
        // 身份证
        if (StringUtils.isNotBlank(item.getProxyUserIdCard())) {
            cmEventApplicant.setProxyUserIdCard(DESUtil.encrypt(item.getProxyUserIdCard()));
        }
        // 统一社会信用代码
        if (StringUtils.isNotBlank(item.getUscc())) {
            cmEventApplicant.setUscc(DESUtil.encrypt(item.getUscc()));
        }
    }

    /**
     * 处理入参
     *
     * @param dto
     */
    protected F doAssemblyParams(F dto) {
        // 设置处理人
        LoginUser loginUser = SecurityUtils.getLoginUser();
        if (null == loginUser) {
            return dto;
        }

        return dto;
    }

    protected void checkParams(F dto) {
        if (StringUtils.isBlank(dto.getOperateType())) {
            return;
        }
        // 1.草稿 2.保存 3.分派 4.召回 5.现场调解 6.结案 7.受理并结案 8.转专窗
        switch (dto.getOperateType()) {
            case "1":
                dto.setDraftFlag(1);
                break;
            case "2":
                dto.setEventState(EventStateEnum.WAIT_ASSIGN.getCode());
                break;
            case "4":
                BaseBusinessDetailVO eventDetail = getEventDetail(dto.getId());
                if (!EventStateEnum.WAIT_ACCEPT.getCode().equals(eventDetail.getEventState())) {
                    throw new ServiceException("操作失败，请刷新重试!");
                }
            case "6":
                dto.setSettleTime(DateTime.now());
                break;
            case "7":
                dto.setSettleTime(DateTime.now());
                break;
            case "8":
                if (null == dto.getChangeWindowConfirmFlag()) {
                    if (null == dto.getChangeWindowId()) {
                        throw new ServiceException("请选择转专窗窗口!");
                    }
                }
                if (Integer.valueOf(1).equals(dto.getChangeWindowConfirmFlag())) {
                    dto.setWindowId(dto.getChangeWindowId());
                }
                break;

        }
        if (null == dto.getDraftFlag()) {
            dto.setDraftFlag(0);
        }

    }

    protected void handerRecord(F dto, EventOperateVO event) {
        dto.setId(event.getId());
        if (StringUtils.isBlank(dto.getOperateType())) {
            return;
        }
        // 1.草稿 2.保存 3.分派 4.召回 5.现场调解 6.结案 7.受理并结案 8.转专窗
        switch (dto.getOperateType()) {
            case "2":
                this.insertRecord(OperatingTypeEnum.REGISTER.getCode(), dto);
                break;
            case "3":
                this.insertRecord(null == dto.getMediatorCommitteeUserId() ?
                        OperatingTypeEnum.ASSIGN.getCode() : OperatingTypeEnum.RECALL_CONFIRM.getCode(), dto);
                this.insertMessage(dto);
                this.insertOrganizationEmployeeMessage(dto, event);
                break;
            case "4":
                this.insertRecord(OperatingTypeEnum.RECALL.getCode(), dto);
                break;
            case "5":
                Integer recordType = getRecordType(dto, event);
                this.insertRecord(recordType, dto);
                break;
            case "6":
                this.insertRecord(OperatingTypeEnum.CLOSE.getCode(), dto);
                break;
            case "7":
                this.insertRecord(getRecordType(dto, event), dto);
                this.insertRecord(OperatingTypeEnum.CLOSE.getCode(), dto);
                break;
            case "8":
                if (null != dto.getChangeWindowConfirmFlag()) {
                    this.insertRecord(OperatingTypeEnum.CHANG_WINDOW_CONFIRM.getCode(), dto);
                    break;
                }
                this.insertRecord(OperatingTypeEnum.CHANG_WINDOW.getCode(), dto);
                break;

        }
    }


    private void insertMessage(F dto) {
        if (null == dto.getId()) {
            return;
        }
        MessageNotifications messageNotifications = new MessageNotifications();
        messageNotifications.setEventCategory(dto.getEventCategory());
        messageNotifications.setEventId(dto.getId());
        if (null != dto.getWindowId()) {
            messageNotifications.setWindowMediationTownshipId(dto.getWindowId());
            messageNotifications.setWindowMediationTownship("1");
        } else if (null != dto.getVillagesSgCenterId()) {
            messageNotifications.setWindowMediationTownshipId(dto.getVillagesSgCenterId());
            messageNotifications.setWindowMediationTownship("2");
        } else if (null != dto.getMediatorCommitteeUserId()) {
            messageNotifications.setWindowMediationTownshipId(dto.getMediatorCommitteeUserId());
            messageNotifications.setWindowMediationTownship("3");
        }

        messageNotifications.setCreateTime(DateTime.now());
        this.ismsgNotificationsService.insertMessageNotifications(messageNotifications);
    }

    private void insertOrganizationEmployeeMessage(F dto, EventOperateVO event) {
        if (null == dto.getId()) {
            return;
        }
        MessageNotifications messageNotifications = new MessageNotifications();
        messageNotifications.setEventCategory(dto.getEventCategory());
        messageNotifications.setEventId(dto.getId());
        messageNotifications.setEventCode(event.getEventCode());
        if (null != dto.getWindowId()) {
            messageNotifications.setWindowMediationTownshipId(dto.getWindowId());
            messageNotifications.setWindowMediationTownship("1");
            List<Long> userIds = this.windowMapper.getUserIdsByWindowId(dto.getWindowId());
            if (CollUtil.isNotEmpty(userIds)) {
                messageNotifications.setAccountId(this.getAccountId(userIds));
            }

        } else if (null != dto.getVillagesSgCenterId()) {
            messageNotifications.setWindowMediationTownshipId(dto.getVillagesSgCenterId());
            messageNotifications.setWindowMediationTownship("2");

        } else if (null != dto.getMediatorCommitteeUserId()) {
            messageNotifications.setWindowMediationTownshipId(dto.getMediatorCommitteeUserId());
            messageNotifications.setWindowMediationTownship("3");
            messageNotifications.setAccountId(this.getAccountId(Arrays.asList(dto.getMediatorCommitteeUserId())));
        }

        messageNotifications.setCreateTime(DateTime.now());
        this.ismsgNotificationsService.insertMessageNotifications(messageNotifications);
        // 发送浙政钉消息
        this.applicationEventPublisher.publishEvent(
                new OrganizationEvent("发送浙政钉消息", messageNotifications));
    }

    private String getAccountId(List<Long> userIds) {
        if (CollUtil.isEmpty(userIds)) {
            return null;
        }
        List<String> accountIds = this.sysUserMapper.selectAccountByUserIds(userIds);
        log.info("accountIds:{}", JSONUtil.toJsonStr(accountIds));
        if (CollUtil.isEmpty(accountIds)) {
            return null;
        }
        accountIds = accountIds.stream().filter(Objects::nonNull).collect(Collectors.toList());
        return StringUtils.getStringByList(accountIds, ",");

    }

    private static <F extends BaseBusinessOperateDTO> Integer getRecordType(F dto, EventOperateVO event) {
        Integer recordType = null;
        if (null != event && EventStateEnum.getWaitAcceptStateList().contains(event.getEventState())) {
            recordType = OperatingTypeEnum.ACCEPT.getCode();
        }
        if (null != event && EventStateEnum.getWaitMediateStateList().contains(event.getEventState())) {
            recordType = OperatingTypeEnum.MEDIATE.getCode();
        }
        dto.setEventState(EventStateEnum.WAIT_CLOSE.getCode());
        return recordType;
    }

    protected void insertRecord(Integer type, F dto) {
        if (null == type || null == dto.getId()) {
            return;
        }
        CmOperatingRecord cmOperatingRecord = new CmOperatingRecord();
        cmOperatingRecord.setEventId(dto.getId());
        cmOperatingRecord.setOperatingType(String.valueOf(type));
        cmOperatingRecord.setEventCategory(dto.getEventCategory());
        cmOperatingRecord.setOperatingTime(DateTime.now());
        cmOperatingRecord.setOperatingUserName(SecurityUtils.getNickName());
        // 转窗口
        IcWindow icWindow = this.windowMapper.selectOne(
                Wrappers.<IcWindow>lambdaQuery().eq(IcWindow::getId, dto.getChangeWindowId()));
        if (null != icWindow) {
            cmOperatingRecord.setChangeWindowId(String.valueOf(icWindow.getId()));
            cmOperatingRecord.setChangeWindowName(icWindow.getWindowName());
        }

        //  操作人所在窗口
        List<Long> windowIdByUserId = this.windowMapper.getWindowIdByUserId(SecurityUtils.getUserId());
        if (CollUtil.isNotEmpty(windowIdByUserId)) {
            IcWindow userWindow = this.windowMapper.selectById(windowIdByUserId.get(0));
            if (null != userWindow) {
                cmOperatingRecord.setOperatingWindowName(userWindow.getWindowName());
            }
        }

        SysDept sysDept = this.deptMapper.selectDeptById(SecurityUtils.getDeptId());
        if (null != sysDept) {
            cmOperatingRecord.setOperatingUserDept(sysDept.getDeptName());
        }
        cmOperatingRecord.setOpinion(dto.getOpinion());
        cmOperatingRecord.setCreateTime(DateTime.now());
        cmOperatingRecord.setCreateBy(SecurityUtils.getUsername());
        this.cmOperatingRecordMapper.insert(cmOperatingRecord);
    }

    protected void getArea(BaseBusinessDetailVO vo) {
        if (StringUtils.isBlank(vo.getAreaId())) {
            return;
        }
        List<Long> areaIds = new LinkedList<>();
        List<String> areaNames = new LinkedList<>();
        areaIds.add(Long.parseLong(vo.getAreaId()));
        areaNames.add(this.areaMapper.selectNameById(Long.parseLong(vo.getAreaId())));
        this.getAreaId(vo.getAreaId(), areaIds, areaNames);
        Collections.reverse(areaIds);
        vo.setAreaIds(areaIds);
        Collections.reverse(areaNames);
        vo.setAreaIdLabel(StringUtils.getStringByList(areaNames, "/"));
    }

    private void getAreaId(String id, List<Long> areaIds, List<String> areaNames) {
        if (null == id) {
            return;
        }
        AreaVO areaVO = this.areaMapper.getAreaPreId(Long.parseLong(id));
        if (null == areaVO) {
            return;
        }
        areaIds.add(Long.parseLong(areaVO.getPreId()));
        areaNames.add(areaVO.getPreAreaName());
        this.getAreaId(areaVO.getPreId(), areaIds, areaNames);
    }

    protected <T> void handlerDictLabel(T newInstance) {
        try {
            if (null == newInstance) {
                return;
            }

            Field[] fields = ReflectUtil.getFields(newInstance.getClass());
            Map<String, Field> fieldMap = Arrays.stream(fields).collect(Collectors.toMap(Field::getName, s -> s));

            for (Field field : fields) {
                field.setAccessible(Boolean.TRUE);
                Object value = field.get(newInstance);
                if (null == value) {
                    continue;
                }

                Field parseField = fieldMap.get(field.getName());
                Field labelField = fieldMap.get(field.getName() + "Label");
                if (null == labelField) {
                    continue;
                }
                DictLabel dictLabel = labelField.getAnnotation(DictLabel.class);
                if (null == dictLabel) {
                    continue;
                }

                labelField.setAccessible(Boolean.TRUE);

                labelField.set(newInstance, this.getDictLabel(dictLabel.value(), value.toString()));

            }

        } catch (Exception e) {
            log.info("回填字典label失败");
            log.info(e.getMessage());
        }

    }

    protected String getDictLabel(String dictType, String dictValue) {

        if (StringUtils.isBlank(dictType) || StringUtils.isBlank(dictValue)) {
            return null;
        }

        List<SysDictData> sysDictData = this.sysDictDataService.selectDictDataList(null);
        if (CollUtil.isEmpty(sysDictData)) {
            return null;
        }

        Map<String, List<SysDictData>> dictDataMap = sysDictData.stream()
                .collect(Collectors.groupingBy(SysDictData::getDictType));

        if (CollUtil.isEmpty(dictDataMap.get(dictType))) {
            return null;
        }

        SysDictData dict = dictDataMap.get(dictType).stream().filter(s -> s.getDictValue().equals(dictValue))
                .findAny().orElse(null);

        return null == dict ? null : dict.getDictLabel();
    }


    public void checkApplicant(List<ApplicantDetailVO> applicantDetailVOList) {
        if (CollUtil.isEmpty(applicantDetailVOList)) {
            throw new ServiceException("结案失败,请填写申请人和被申请人!");
        }
        List<ApplicantDetailVO> applicants = applicantDetailVOList.stream()
                .filter(item -> Integer.valueOf(1).equals(item.getApplicantCategory())).collect(
                        Collectors.toList());
        if (CollUtil.isEmpty(applicants)) {
            throw new ServiceException("结案失败,请填写申请人!");
        }
        this.checkApplicantInfo(applicants, "结案失败,请完善申请人信息!");
        List<ApplicantDetailVO> applicantList = applicantDetailVOList.stream()
                .filter(item -> Integer.valueOf(2).equals(item.getApplicantCategory())).collect(
                        Collectors.toList());
        if (CollUtil.isEmpty(applicantList)) {
            throw new ServiceException("结案失败,请填写被申请人!");
        }
        this.checkApplicantInfo(applicantList, "结案失败,请完善被申请人信息!");

    }

    public void checkApplicantInfo(List<ApplicantDetailVO> applicants, String msg) {
        applicants.forEach(item -> {
            if (StringUtils.isBlank(item.getApplicantType())) {
                throw new ServiceException(msg);
            }
            if (Integer.valueOf(1).equals(item.getApplicantType())) {
                if (StringUtils.isBlank(item.getName()) ||
                        StringUtils.isBlank(item.getIdCardType()) ||
                        StringUtils.isBlank(item.getIdCard()) ||
                        StringUtils.isBlank(item.getSex()) ||
                        null == item.getAge() ||
                        StringUtils.isBlank(item.getNationality()) ||
                        StringUtils.isBlank(item.getPhone()) ||
                        StringUtils.isBlank(item.getResidentialAddress()) ||
                        StringUtils.isBlank(item.getAttributionAddress())) {
                    throw new ServiceException(msg);
                }
            } else if (Integer.valueOf(2).equals(item.getApplicantType())) {
                if (StringUtils.isBlank(item.getCompanyName()) ||
                        StringUtils.isBlank(item.getUscc()) ||
                        StringUtils.isBlank(item.getCompanyAddress()) ||
                        StringUtils.isBlank(item.getName()) ||
                        StringUtils.isBlank(item.getIdCardType()) ||
                        StringUtils.isBlank(item.getIdCard()) ||
                        StringUtils.isBlank(item.getSex()) ||
                        StringUtils.isBlank(item.getPhone())) {
                    throw new ServiceException(msg);
                }
            } else if (Integer.valueOf(3).equals(item.getApplicantType())) {
                if (StringUtils.isBlank(item.getCompanyName()) ||
                        StringUtils.isBlank(item.getCompanyAddress()) ||
                        StringUtils.isBlank(item.getName()) ||
                        StringUtils.isBlank(item.getIdCardType()) ||
                        StringUtils.isBlank(item.getIdCard()) ||
                        StringUtils.isBlank(item.getSex()) ||
                        StringUtils.isBlank(item.getPhone())) {
                    throw new ServiceException(msg);
                }
            }

            if (Integer.valueOf(1).equals(item.getIsHaveProxyUser())) {
                if (StringUtils.isBlank(item.getProxyUserName()) ||
                        StringUtils.isBlank(item.getProxyUserSex()) ||
                        StringUtils.isBlank(item.getProxyUserIdCardType()) ||
                        StringUtils.isBlank(item.getProxyUserIdCard()) ||
                        StringUtils.isBlank(item.getProxyUserPhone())) {
                    throw new ServiceException(msg);
                }
            }


        });
    }

    protected void checkDossier(List<CmEventFile> cmEventFilesVO, String mediationResult) {
        if (StringUtils.isBlank(mediationResult)) {
            throw new ServiceException("结案失败,请选择调解结果!");
        }
        if (!String.valueOf(1).equals(mediationResult)) {
            return;
        }
        // 1.人民调解申请书或人民调解受理登记表
        // 2.人民调解当事人权利义务告知书
        // 3.当事人身份证明
        // 8.人民调解协议书
        // 13.封底
        if (CollUtil.isEmpty(cmEventFilesVO)) {
            throw new ServiceException("结案失败,请上传卷宗!");
        }
        List<String> fileTypes = Arrays.asList("1", "2", "3", "8", "13");
        List<String> fileTypeVOs = cmEventFilesVO.stream().map(CmEventFile::getFileType).collect(Collectors.toList());
        if (!fileTypes.stream().allMatch(fileTypeVOs::contains)) {
            throw new ServiceException("结案失败,请上传卷宗!");
        }

    }
}
